import axios from 'axios';
import qs from 'qs';
import _ from 'lodash';
import { API_BASE_URl } from '@/constants';

const { NODE_ENV } = process.env;

const CONTENT_TYPES = {
  1: 'application/json',
  2: 'application/x-www-form-url-urlencode',
  3: 'multipart/form-data'
};

const instance = axios.create();

const repeatMap = {};

function ajax(url, options) {
  const method = (options.method || 'post').toLowerCase();
  const repeatKey = `${url} ${method} ${JSON.stringify(options.data)}`;
  if (repeatMap[repeatKey]) {
    if (NODE_ENV === 'development') {
      return Promise.reject(new Error('请求太频繁，请稍后再试!'));
    }
    return repeatMap[repeatKey];
  }
  const headers = {};
  if (options.contentType) {
    headers['Content-Type'] = CONTENT_TYPES[options.contentType] || options.contentType;
  }
  const config = {
    url,
    method,
    baseURL: options.baseURL || API_BASE_URl,
    withCredentials: _.isBoolean(options.withCredentials) ? options.withCredentials : true,
    headers: { ...headers, ...(options.headers || {}) }
  };
  if (options.responseType) {
    config.responseType = options.responseType;
  }
  if (['get', 'delete'].indexOf(method) > -1) {
    config.data = true;
    config.params = options.data;
  } else if (options.contentType === 2) {
    config.data = qs.stringify(options.data);
  } else {
    config.data = options.data;
  }
  // 自定义修改config
  if (_.isFunction(options.adjustConfig)) {
    options.adjustConfig(config);
  }
  const promise = instance(config).then(({ headers: resHeaders, data: resData }) => {
    if (_.isFunction(options.doneHandler)) {
      return options.doneHandler(resData);
    }
    if (options.responseType === 'blob') {
      return { headers: resHeaders, data: resData };
    }
    const { code, message, data } = resData;
    if (code === 200) {
      return data;
    }
    return Promise.reject(new Error(message));
  }).catch((error) => {
    if (_.isFunction(options.failHandler)) {
      return options.failHandler(error);
    }
    return Promise.reject(error);
  }).finally(() => {
    if (repeatMap[repeatKey]) {
      delete repeatMap[repeatKey];
    }
  });
  repeatMap[repeatKey] = promise;
  return promise;
}

function createAjax(config) {
  const result = {};
  (config.items || []).forEach((item) => {
    result[item.key] = function (params) {
      let url = (item.prefix || config.prefix || '') + (item.url || '');
      let data = params;
      // 解析restful风格的请求，eg：/x/:y/:z
      if (/\/:/.test(url)) {
        const excludes = [];
        url = url.replace(/:([^/]+)/g, (match, p1) => {
          if (_.has(data, p1)) {
            excludes.push(p1);
            return data[p1];
          }
          return match;
        });
        data = _.omit(data, excludes);
      }
      return ajax(
        url,
        {
          data,
          ..._.omit(config, ['prefix', 'items']),
          ..._.omit(item, ['key', 'url', 'prefix'])
        }
      );
    };
  });
}

export {
  ajax,
  createAjax
};
